interface Parm {
  dbName: string;
  objName: string;
  param: any;
  response: any;
  versions?: number;
}

export default class {
  private db: IDBDatabase | null;

  constructor() {
    this.db = null;
  }

  getType(val: any): boolean {
    return typeof val === 'object';
  }

  // 打开数据库
  open(parm: Parm): Promise<void> {
    return new Promise((res, rej) => {
      const request = window.indexedDB.open(parm.dbName, parm.versions);
      request.onerror = (event) => {
        console.log(event);
        // 错误处理
        rej();
        console.log('打开数据库报错');
      };
      request.onsuccess = (event) => {
        this.db = request.result;
        console.log('打开数据库成功');
        res();
        // 成功处理
      };
      // 数据库更新时的回调
      request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
        console.log('数据库更新成功');
        this.db = (event.target as IDBOpenDBRequest).result;
        this.createdDB(parm);
      };
    });
  }

  // 创建库表
  createdDB(parm: Parm): void {
    if (!this.db) return;
    if (!this.db.objectStoreNames.contains(parm.objName)) {
      this.db.createObjectStore(parm.objName, {
        keyPath: 'id',
      });
      // objectStore.createIndex("data", "data", { unique: false });
      // unique name可能会重复
    }
  }

  // 新增（不需要使用）
  async add(parm: Parm): Promise<Event> {
    await this.open(parm);
    return new Promise((res, rej) => {
      const type = this.getType(parm.param);
      const type1 = this.getType(parm.response);
      const transaction = this.db!.transaction([parm.objName], 'readwrite');
      const objectStore = transaction.objectStore(parm.objName);

      // 用户读取数据，参数是主键
      const request = objectStore.add({
        id: type ? JSON.stringify(parm.param) : parm.param,
        data: type1 ? JSON.stringify(parm.response) : parm.response,
      });
      console.log(request);

      request.onsuccess = (event) => {
        res(event);
        console.log('数据写入成功');
      };

      request.onerror = (event) => {
        rej();
        console.log('数据写入失败');
      };
    });
  }

  // 读取库表数据
  read(parm: Parm): Promise<any> {
    return new Promise((res, rej) => {
      const type = this.getType(parm.param);

      const transaction = this.db!.transaction([parm.objName]);
      const objectStore = transaction.objectStore(parm.objName);
      // 用户读取数据，参数是主键
      const request = objectStore.get(type ? JSON.stringify(parm.param) : parm.param);

      request.onerror = (event) => {
        console.log('事务失败');
        rej();
      };

      request.onsuccess = (event) => {
        if (request.result) {
          const data = JSON.parse(request.result.data);
          res(data);
        } else {
          res(request.result);
          console.log('未获得数据记录');
        }
      };
    });
  }

  // 修改库表数据,但是因为创建数据库时直接创建了库表,所以无论是添加还是修改都掉这个就可以了.
  update(parm: Parm): Promise<void> {
    return new Promise((res, rej) => {
      const type = this.getType(parm.param);
      const type1 = this.getType(parm.response);

      console.log(parm);
      const request = this.db!
        .transaction([parm.objName], 'readwrite')
        .objectStore(parm.objName)
        .put({
          id: type ? JSON.stringify(parm.param) : parm.param,
          data: type1 ? JSON.stringify(parm.response) : parm.response,
        });

      request.onsuccess = (event) => {
        res();
        console.log('数据更新成功');
      };

      request.onerror = (event) => {
        rej();
        console.log('数据更新失败');
      };
    });
  }

  // 删除某个表的数据
  async remove(parm: Parm): Promise<void> {
    await this.open(parm);

    return new Promise((res, rej) => {
      const type = this.getType(parm.param);

      const request = this.db!
        .transaction([parm.objName], 'readwrite')
        .objectStore(parm.objName)
        .delete(type ? JSON.stringify(parm.param) : parm.param);

      request.onsuccess = (event) => {
        res();
        console.log('数据删除成功');
      };

      request.onerror = (event) => {
        rej();
        console.log('数据删除失败');
      };
    });
  }
}